home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
pcl_src.zoo
/
iterate.lsp
< prev
next >
Wrap
Lisp/Scheme
|
1992-07-09
|
63KB
|
1,270 lines
;;;-*- Package: ITERATE; Syntax: Common-Lisp; Base: 10 -*-
;;;
;;; *************************************************************************
;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
;;; All rights reserved.
;;;
;;; Use and copying of this software and preparation of derivative works
;;; based upon this software are permitted. Any distribution of this
;;; software or derivative works must comply with all applicable United
;;; States export control laws.
;;;
;;; This software is made available AS IS, and Xerox Corporation makes no
;;; warranty about the software, its performance or its conformity to any
;;; specification.
;;;
;;; Any person obtaining a copy of this software is requested to send their
;;; name and post office or electronic mail address to:
;;; CommonLoops Coordinator
;;; Xerox PARC
;;; 3333 Coyote Hill Rd.
;;; Palo Alto, CA 94304
;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
;;;
;;; Suggestions, comments and requests for improvements are also welcome.
;;; *************************************************************************
;;;
;;; Original source {pooh/n}<pooh>vanmelle>lisp>iterate;4 created 27-Sep-88 12:35:33
(in-package :iterate :use '(:lisp :walker))
(export '(iterate iterate* gathering gather with-gathering interval elements
list-elements list-tails plist-elements eachtime while until
collecting joining maximizing minimizing summing
*iterate-warnings*))
(defvar *iterate-warnings* :any "Controls whether warnings are issued for iterate/gather forms that aren't optimized.
NIL => never; :USER => those resulting from user code; T => always, even if it's the iteration macro that's suboptimal."
)
;;; ITERATE macro
(defmacro iterate (clauses &body body &environment env)
(optimize-iterate-form clauses body env))
(defun
simple-expand-iterate-form
(clauses body)
;; Expand ITERATE. This is the "formal semantics" expansion, which we never
;; use.
(let*
((block-name (gensym))
(bound-var-lists (mapcar #'(lambda (clause)
(let ((names (first clause)))
(if (listp names)
names
(list names))))
clauses))
(generator-vars (mapcar #'(lambda (clause)
(declare (ignore clause))
(gensym))
clauses)))
`(block ,block-name
(let*
,(mapcan #'(lambda (gvar clause var-list)
; For each clause, bind a
; generator temp to the clause,
; then bind the specified
; var(s)
(cons (list gvar (second clause))
(copy-list var-list)))
generator-vars clauses bound-var-lists)
;; Note bug in formal semantics: there can be declarations in the head
;; of BODY; they go here, rather than inside loop
(loop
,@(mapcar
#'(lambda (var-list gen-var)
; Set each bound variable (or
; set of vars) to the result of
; calling the corresponding
; generator
`(multiple-value-setq
,var-list
(funcall ,gen-var #'(lambda nil (return-from
,block-name)))))
bound-var-lists generator-vars)
,@body)))))
(defparameter *iterate-temp-vars-list*
'(iterate-temp-1 iterate-temp-2 iterate-temp-3 iterate-temp-4
iterate-temp-5 iterate-temp-6 iterate-temp-7 iterate-temp-8)
"Temp var names used by ITERATE expansions.")
(defun
optimize-iterate-form
(clauses body iterate-env)
(let*
((temp-vars *iterate-temp-vars-list*)
(block-name (gensym))
(finish-form `(return-from ,block-name))
(bound-vars (mapcan #'(lambda (clause)
(let ((names (first clause)))
(if (listp names)
(copy-list names)
(list names))))
clauses))
iterate-decls generator-decls update-forms bindings leftover-body)
(do ((tail bound-vars (cdr tail)))
((null tail))
; Check for duplicates
(when (member (car tail)
(cdr tail))
(warn "Variable appears more than once in ITERATE: ~S" (car tail))))
(flet
((get-iterate-temp nil
;; Make temporary var. Note that it is ok to re-use these symbols
;; in each iterate, because they are not used within BODY.
(or (pop temp-vars)
(gensym))))
(dolist (clause clauses)
(cond
((or (not (consp clause))
(not (consp (cdr clause))))
(warn "Bad syntax in ITERATE: clause not of form (var iterator): ~S"
clause))
(t
(unless (null (cddr clause))
(warn
"Probable parenthesis error in ITERATE clause--more than 2 elements: ~S"
clause))
(multiple-value-bind
(let-body binding-type let-bindings localdecls otherdecls extra-body)
(expand-into-let (second clause)
'iterate iterate-env)
;; We have expanded the generator clause and parsed it into its LET
;; pieces.
(prog*
((vars (first clause))
gen-args renamed-vars)
(setq vars (if (listp vars)
(copy-list vars)
(list vars)))
; VARS is now a (fresh) list of
; all iteration vars bound in
; this clause
(cond
((eq let-body :abort)
; Already issued a warning
; about malformedness
)
((null (setq let-body (function-lambda-p let-body 1)))
; Not of the expected form
(let ((generator (second clause)))
(cond ((and (consp generator)
(fboundp (car generator)))
; It looks ok--a macro or
; function here--so the guy who
; wrote it just didn't do it in
; an optimizable way
(maybe-warn :definition "Could not optimize iterate clause ~S because generator not of form (LET[*] ... (FUNCTION (LAMBDA (finish) ...)))"
generator))
(t ; Perhaps it's just a
; misspelling? Probably user
; error
(maybe-warn :user
"Iterate operator in clause ~S is not fboundp."
generator)))
(setq let-body :abort)))
(t
;; We have something of the form #'(LAMBDA (finisharg) ...),
;; possibly with some LET bindings around it. LET-BODY =
;; ((finisharg) ...).
(setq let-body (cdr let-bod